加入購物車的按鈕要怎麼寫測試?
要用到 vuex 嗎?
如果用的話,actions, state, mutations 要怎麼測?
每次開發總是想得太遠,做得太少?
寫測試的目的之一,我想是你有多少能力測多少事
已最小可行性當作出發點吧
所以首先當然是拋開 vuex,
設想一下,當我們今天要加入購物車
最簡單的作法是什麼?
就是在 data property 多一個地方可以存就好了
然後,有個按鈕會把選到的產品 id 加到購物車的 Object 裡面
所以我們一開始的測試可以這樣寫
it('按加入,要把產品 id 和數量加到購物車', () => {
expectTo.click('.add-to-cart-button')
expect(wrapper.vm.cart.products.length).toEqual(1)
expect(wrapper.vm.cart.products[0].id).toEqual(1)
expect(wrapper.vm.cart.products[0].count).toEqual(1)
})
it('如果產品已經在購物車,數量 +1', () => {
expectTo.click('.add-to-cart-button')
expect(wrapper.vm.cart.products.length).toEqual(1)
expect(wrapper.vm.cart.products[0].id).toEqual(1)
expect(wrapper.vm.cart.products[0].count).toEqual(1)
expectTo.click('.add-to-cart-button')
expectTo.click('.add-to-cart-button')
expectTo.click('.add-to-cart-button')
expect(wrapper.vm.cart.products.length).toEqual(1)
expect(wrapper.vm.cart.products[0].id).toEqual(1)
expect(wrapper.vm.cart.products[0].count).toEqual(4)
})
<button class="add-to-cart-button" @click="addToCart"> 加入購物車</button>
methods: {
addToCart () {
// 加到 cart object
}
},
data: {
...
cart: {
products: []
},
}
有了這個雛形之後,我想多做一點改變
把購物車用 vuex 去實作
在 /store 裡面新增一個 index.js
簡單放一點功能
export const state = () => ({
cart: {
products: []
}
})
export const mutations = {
add (state, productId) {
let product = state.cart.products.find(
product => product.id === productId
)
product ?
product.count += 1 :
this.cart.products.push({id: productId, count: 1})
}
}
那我們的原本加入購物車的邏輯就要調整
回去 LandingPage.vue, 把 vuex 設定近來
import { mapState, mapMutations } from 'vuex'
export default {
computed: {
...mapState(['cart'])
// 省略其他的內容
},
methods: {
...mapMutations(['add']),
// 這樣就可以直接使用了
addToCart () {
this.add(this.selectedProductId)
}
// 省略其他的內容
}
}
這時候會發現我們的測試壞掉了,這是正常的
我們的測試只是沒設定 Vuex 而已
這邊我們要怎麼修呢
先讓 vue 知道我們要用 vuex
import { mount, shallow, createLocalVue } from 'vue-test-utils'
import Vuex from 'vuex'
const localVue = createLocalVue()
localVue.use(Vuex)
再來在 beforeEach 的區塊,mock vuex 的所有內容
beforeEach(() => {
mutations = {
// 直接用個 stub function
add: jest.fn(),
}
store = new Vuex.Store({
state: {}, // 根本連什麼資料都不用設定
mutations
})
}
然後我們的測試,只需要確認我們的 stub function 有被使用就好
it('按加入,要觸發加入購物車的 action', () => {
expectTo.click('.add-to-cart-button')
expect(mutations.add).toHaveBeenCalled()
})
基本上我們把功能 mock 住,就代表我們信任那個 module
這個信任是很盲目的,還有時間的話 vuex 要單獨自己寫測試
這邊就建議用嚴格的 unit testing
畢竟是單純的邏輯, 跟畫面沒有關係